package com.java.shop.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java.common.to.SkuReductionTo;
import com.java.common.utils.PageUtils;
import com.java.common.utils.Query;
import com.java.common.utils.R;
import com.java.shop.product.dao.SkuInfoDao;
import com.java.shop.product.entity.*;
import com.java.shop.product.feign.CouponFeignService;
import com.java.shop.product.feign.ThirdPartFeignService;
import com.java.shop.product.service.*;
import com.java.shop.product.vo.*;
import com.java.shop.product.webvo.SkuItemVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {
    @Autowired
    SkuImagesService skuImagesService;

    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    SpuInfoDescService spuInfoDescService;

    @Autowired
    ProductAttrValueService productAttrValueService;

    @Autowired
    AttrGroupService attrGroupService;

    @Autowired
    SpuInfoService spuInfoService;

    @Autowired
    CouponFeignService couponFeignService;

    @Autowired
    ThirdPartFeignService thirdPartFeignService;

    @Autowired
    ThreadPoolExecutor executor;




    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                new QueryWrapper<SkuInfoEntity>()
        );
        return new PageUtils(page);
    }

    @Override
    public void saveSkuInfo(SpuInfoEntity spuInfoEntity, List<Skus> skus) {
        //6.1）sku的基本信息  pms_sku_info
        //6.2）保存sku的图片信息  pms_sku_images
        //6.3）sku销售属性信息 pms_sku_sale_attr_value
        //6.4）sku的满减优惠信息  shop-sms->sms_sku_full_reduction\sms_sku_ladder\sms_member_price
        if(skus != null && skus.size() > 0){
            skus.forEach(item->{
                String defaultImg = "";
                for(Images image : item.getImages()){
                    if(image.getDefaultImg() == 1){
                        defaultImg = image.getImgUrl();
                    }
                }
                //6.1）保存sku的基本信息  pms_sku_info
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(item,skuInfoEntity);
                skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSpuId(spuInfoEntity.getId());
                skuInfoEntity.setSkuDefaultImg(defaultImg);
                this.save(skuInfoEntity);
                Long skuId = skuInfoEntity.getSkuId();

                //6.2）保存sku的图片信息  pms_sku_images
                List<Images> images = item.getImages();
                List<SkuImagesEntity> collect = images.stream().map(img -> {
                    SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                    skuImagesEntity.setSkuId(skuId);
                    skuImagesEntity.setImgUrl(img.getImgUrl());
                    skuImagesEntity.setDefaultImg(img.getDefaultImg());
                    return skuImagesEntity;
                }).filter(img-> !StringUtils.isEmpty(img.getImgUrl())).collect(Collectors.toList());
                skuImagesService.saveBatch(collect);

                //6.3）sku销售属性信息 pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();
                List<SkuSaleAttrValueEntity> attrList = attrs.stream().map(attr -> {
                    SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                    BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                    skuSaleAttrValueEntity.setSkuId(skuId);
                    return skuSaleAttrValueEntity;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(attrList);


                //6.4）sku的满减优惠信息  shop-sms->sms_sku_full_reduction\sms_sku_ladder\sms_member_price
                SkuReductionTo skuReductionTo = new SkuReductionTo();
                BeanUtils.copyProperties(item,skuReductionTo);
                skuReductionTo.setSkuId(skuId);
                //过滤数据
                if(skuReductionTo.getFullCount() > 0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0"))==1){
                    //TODO 远程调用coupon模块分布式事务处理
                    R r = couponFeignService.saveSkuReduction(skuReductionTo);
                    if(r.getCode() != 0){
                        log.error("SkuInfoServiceImpl:saveSkuInfo中调用远程方法couponFeignService.saveSkuReduction(skuReductionTo)失败");
                    }
                }
            });
        }
    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SkuInfoEntity> wrapper = new QueryWrapper<>();
        //如果分类Id存在
        String catelogId = (String) params.get("catelogId");
        if(!StringUtils.isEmpty(catelogId) && !"0".equals(catelogId)){
            wrapper.eq("catalog_id",catelogId);
        }


        //如果品牌Id存在
        String brandId = (String) params.get("brandId");
        if(!StringUtils.isEmpty(brandId) && !"0".equals(brandId)){
            wrapper.eq("brand_id",brandId);
        }


        //检索条件
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and(w->{
                w.eq("sku_id",key).or().like("sku_name",key);
            });
        }

        //价格区间
        String min = (String) params.get("min");
        if(!StringUtils.isEmpty(min) && !"0".equals(min)){
            wrapper.ge("price",min);
        }

        String max = (String) params.get("max");
        if(!StringUtils.isEmpty(max) && !"0".equals(max)){
            wrapper.le("price",max);
        }

        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),wrapper
        );

        return new PageUtils(page);
    }

    /**
     * 知识点，使用异步编排，防止数据渲染不完全（主线程跑得快，数据还未查询完就返回了，导致数据渲染不完全，所以使用异步编排）
     * 商品详情页数据
     * @param skuId
     * @return
     */
    @Override
    public SkuItemVo getItem(Long skuId) {
        SkuItemVo vo = new SkuItemVo();
        CompletableFuture<SkuInfoEntity> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            /* 获得商品基本信息 */
            SkuInfoEntity sku = this.getById(skuId);
            vo.setInfo(sku);
            return sku;
        }, executor);


        CompletableFuture<Void> descFuture = skuInfoFuture.thenAcceptAsync(sku -> {
            /* 获得spu描述 */
            SpuInfoDescEntity spuDesc = spuInfoDescService.getById(sku.getSpuId());
            vo.setDesp(spuDesc);
        }, executor);

        CompletableFuture<Void> saleAttrFuture = skuInfoFuture.thenAcceptAsync(sku -> {
            /* 获得商品销售属性 */
            List<SkuItemVo.SkuItemSaleAttrVo> skuItemSaleAttrVo = skuSaleAttrValueService.getSaleAttrBySpuId(sku.getSpuId());
            vo.setSaleAttr(skuItemSaleAttrVo);
        }, executor);

        CompletableFuture<Void> attrFuture = skuInfoFuture.thenAcceptAsync(sku->{
            /* 获得商品spu属性分组和对应的spu属性 */
            List<SkuItemVo.SpuItemAttrGroupVo> attrGroupVos = attrGroupService.getAttrGroupWithAttrsBySpuId(sku.getSpuId(),sku.getCatalogId());
            vo.setGroupAttr(attrGroupVos);
        },executor);

        CompletableFuture<Void> imagesFuture = CompletableFuture.runAsync(()->{
            /* 获得商品图片 */
            List<SkuImagesEntity> images = skuImagesService.list(new QueryWrapper<SkuImagesEntity>().eq("sku_id", skuId));
            vo.setImages(images);
        },executor);

        CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(()->{
            /* 获得是否是正在秒杀的商品或是否在最近三天是否会上架秒杀活动 */
            R r = thirdPartFeignService.getCurrentSeckillSkus();
            if(r.getCode() == 0 && r.getData() != null){
                List<SeckillItemVo> seckillVo = JSON.parseObject(r.getData(), new TypeReference<List<SeckillItemVo>>() {});
                Map<Long, SeckillItemVo> map = seckillVo.stream().map(item->setSeckillItemVoType(item)).collect(Collectors.toMap(SeckillItemVo::getSkuId, item -> item));
                SeckillItemVo seckillItemVo = map.get(skuId);
                if(seckillItemVo != null) vo.setSeckillVo(seckillItemVo);
            }
        },executor);

        try {
            //等待所有异步编排的线程执行完毕
            CompletableFuture.allOf(descFuture,saleAttrFuture,attrFuture,imagesFuture,seckillFuture).get();
        } catch (Exception e) {
            log.error("SkuInfoServiceImpl::getItem异步编排时错误{}",e.getMessage());
        }

        return vo;
    }

    private SeckillItemVo setSeckillItemVoType(SeckillItemVo item) {
        Long startTime = item.getStartTime();
        Long endTime = item.getEndTime();
        long now = new Date().getTime();
        if(now>=startTime && now<=endTime){
            item.setType(2);
        }else if(now< startTime){
            item.setType(1);
        }
        Date date = new Date(startTime);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        item.setStartTimeStr(dateFormat.format(date));
        return item;
    }

    @Override
    public Map<Long, BigDecimal> getNewPriceBySkuIds(List<Long> skuIds) {
        List<SkuPriceVo> vos = baseMapper.getPriceBySkuIds(skuIds);
        return vos.stream().collect(Collectors.toMap(SkuPriceVo::getSkuId, SkuPriceVo::getPrice));
    }

    @Override
    public Map<Long, SkuInfoEntity> getSkuInfoByIds(List<Long> skuIds) {
        List<SkuInfoEntity> entitys = this.list(new QueryWrapper<SkuInfoEntity>().in("sku_id", skuIds));
        return entitys.stream().collect(Collectors.toMap(SkuInfoEntity::getSkuId, sku->sku));
    }
}